const express = require('express');
const router = express.Router();
const fs = require('fs').promises;
const path = require('path');
const { exec } = require('child_process');
const util = require('util');
const { verifyAdmin } = require('../middleware/auth');

const execPromise = util.promisify(exec);

// Nginx相关配置
const NGINX_SITES_PATH = '/etc/nginx/sites-available';
const NGINX_ENABLED_PATH = '/etc/nginx/sites-enabled';
const NGINX_CONFIG_PATH = '/etc/nginx/nginx.conf';

/**
 * @route   GET /api/nginx/sites
 * @desc    获取所有Nginx站点配置
 * @access  私有
 */
router.get('/sites', async (req, res) => {
  try {
    // 检查Nginx是否安装
    try {
      await execPromise('which nginx');
    } catch (error) {
      return res.status(400).json({ error: 'Nginx未安装' });
    }
    
    // 检查配置目录是否存在
    try {
      await fs.access(NGINX_SITES_PATH);
    } catch (error) {
      return res.status(400).json({ error: 'Nginx配置目录不存在' });
    }
    
    // 获取所有可用站点
    const availableSites = await fs.readdir(NGINX_SITES_PATH);
    
    // 获取所有已启用站点
    let enabledSites = [];
    try {
      enabledSites = await fs.readdir(NGINX_ENABLED_PATH);
    } catch (error) {
      console.error('无法访问已启用站点目录:', error);
    }
    
    // 构建站点列表，包含详细信息
    const sites = await Promise.all(availableSites.map(async (siteName) => {
      const configPath = path.join(NGINX_SITES_PATH, siteName);
      const stats = await fs.stat(configPath);
      const content = await fs.readFile(configPath, 'utf8');
      
      // 提取server_name和端口
      const serverNameMatch = content.match(/server_name\s+([^;]*);/);
      const listenMatch = content.match(/listen\s+([^;]*);/);
      
      const serverName = serverNameMatch ? serverNameMatch[1].trim() : '未指定';
      const port = listenMatch ? listenMatch[1].trim() : '80';
      
      // 提取root路径
      const rootMatch = content.match(/root\s+([^;]*);/);
      const rootPath = rootMatch ? rootMatch[1].trim() : '未指定';
      
      // 检查是否启用SSL
      const sslEnabled = content.includes('ssl_certificate');
      
      return {
        name: siteName,
        enabled: enabledSites.includes(siteName),
        serverName,
        port,
        rootPath,
        sslEnabled,
        size: stats.size,
        modifiedTime: stats.mtime.getTime()
      };
    }));
    
    res.json(sites);
  } catch (error) {
    res.status(500).json({ error: `获取Nginx站点配置失败: ${error.message}` });
  }
});

/**
 * @route   GET /api/nginx/site/:name
 * @desc    获取指定站点的配置内容
 * @access  私有
 */
router.get('/site/:name', async (req, res) => {
  try {
    const siteName = req.params.name;
    const configPath = path.join(NGINX_SITES_PATH, siteName);
    
    try {
      await fs.access(configPath);
    } catch (error) {
      return res.status(404).json({ error: '站点配置不存在' });
    }
    
    const content = await fs.readFile(configPath, 'utf8');
    
    res.json({
      name: siteName,
      content
    });
  } catch (error) {
    res.status(500).json({ error: `获取站点配置失败: ${error.message}` });
  }
});

/**
 * @route   POST /api/nginx/site
 * @desc    创建或更新站点配置
 * @access  私有 (仅管理员)
 */
router.post('/site', verifyAdmin, async (req, res) => {
  try {
    const { name, content } = req.body;
    
    if (!name || !content) {
      return res.status(400).json({ error: '未提供站点名称或配置内容' });
    }
    
    // 验证配置名称（防止路径遍历）
    if (!/^[a-zA-Z0-9\-_.]+$/.test(name)) {
      return res.status(400).json({ error: '无效的站点名称' });
    }
    
    const configPath = path.join(NGINX_SITES_PATH, name);
    
    // 写入配置文件
    await fs.writeFile(configPath, content, 'utf8');
    
    // 测试配置是否有效
    try {
      await execPromise('nginx -t');
    } catch (error) {
      // 配置测试失败，删除刚才写入的配置
      await fs.unlink(configPath);
      return res.status(400).json({ error: `Nginx配置测试失败: ${error.stderr}` });
    }
    
    res.json({ message: '站点配置已保存' });
  } catch (error) {
    res.status(500).json({ error: `保存站点配置失败: ${error.message}` });
  }
});

/**
 * @route   DELETE /api/nginx/site/:name
 * @desc    删除站点配置
 * @access  私有 (仅管理员)
 */
router.delete('/site/:name', verifyAdmin, async (req, res) => {
  try {
    const siteName = req.params.name;
    
    // 验证配置名称（防止路径遍历）
    if (!/^[a-zA-Z0-9\-_.]+$/.test(siteName)) {
      return res.status(400).json({ error: '无效的站点名称' });
    }
    
    const configPath = path.join(NGINX_SITES_PATH, siteName);
    const enabledPath = path.join(NGINX_ENABLED_PATH, siteName);
    
    // 检查配置是否存在
    try {
      await fs.access(configPath);
    } catch (error) {
      return res.status(404).json({ error: '站点配置不存在' });
    }
    
    // 如果站点已启用，先禁用
    try {
      await fs.access(enabledPath);
      await fs.unlink(enabledPath);
    } catch (error) {
      // 站点未启用，忽略错误
    }
    
    // 删除配置文件
    await fs.unlink(configPath);
    
    // 重新加载Nginx配置
    try {
      await execPromise('nginx -s reload');
    } catch (error) {
      return res.status(500).json({ error: `Nginx重新加载失败: ${error.stderr}` });
    }
    
    res.json({ message: '站点配置已删除' });
  } catch (error) {
    res.status(500).json({ error: `删除站点配置失败: ${error.message}` });
  }
});

/**
 * @route   POST /api/nginx/site/:name/toggle
 * @desc    启用或禁用站点
 * @access  私有 (仅管理员)
 */
router.post('/site/:name/toggle', verifyAdmin, async (req, res) => {
  try {
    const siteName = req.params.name;
    const { enable } = req.body;
    
    if (enable === undefined) {
      return res.status(400).json({ error: '未指定启用或禁用' });
    }
    
    // 验证配置名称（防止路径遍历）
    if (!/^[a-zA-Z0-9\-_.]+$/.test(siteName)) {
      return res.status(400).json({ error: '无效的站点名称' });
    }
    
    const configPath = path.join(NGINX_SITES_PATH, siteName);
    const enabledPath = path.join(NGINX_ENABLED_PATH, siteName);
    
    // 检查配置是否存在
    try {
      await fs.access(configPath);
    } catch (error) {
      return res.status(404).json({ error: '站点配置不存在' });
    }
    
    if (enable) {
      // 启用站点
      try {
        await fs.symlink(configPath, enabledPath);
      } catch (error) {
        // 如果符号链接已存在，忽略错误
        if (error.code !== 'EEXIST') {
          throw error;
        }
      }
    } else {
      // 禁用站点
      try {
        await fs.unlink(enabledPath);
      } catch (error) {
        // 如果符号链接不存在，忽略错误
        if (error.code !== 'ENOENT') {
          throw error;
        }
      }
    }
    
    // 测试配置是否有效
    try {
      await execPromise('nginx -t');
    } catch (error) {
      // 如果配置测试失败并且是启用操作，恢复到之前的状态
      if (enable) {
        try {
          await fs.unlink(enabledPath);
        } catch (err) {
          // 忽略删除错误
        }
      }
      return res.status(400).json({ error: `Nginx配置测试失败: ${error.stderr}` });
    }
    
    // 重新加载Nginx配置
    await execPromise('nginx -s reload');
    
    res.json({
      message: enable ? '站点已启用' : '站点已禁用'
    });
  } catch (error) {
    res.status(500).json({ error: `${error.message}` });
  }
});

/**
 * @route   GET /api/nginx/templates
 * @desc    获取预设的站点模板
 * @access  私有
 */
router.get('/templates', async (req, res) => {
  // 预定义的站点配置模板
  const templates = [
    {
      name: 'static',
      label: '静态网站',
      template: `server {
    listen 80;
    server_name example.com;
    
    root /var/www/html;
    index index.html;
    
    location / {
        try_files $uri $uri/ =404;
    }
}`
    },
    {
      name: 'php',
      label: 'PHP站点',
      template: `server {
    listen 80;
    server_name example.com;
    
    root /var/www/html;
    index index.php index.html;
    
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
    
    location ~ \\.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
    }
}`
    },
    {
      name: 'nodejs',
      label: 'Node.js应用',
      template: `server {
    listen 80;
    server_name example.com;
    
    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}`
    },
    {
      name: 'ssl',
      label: '启用SSL',
      template: `server {
    listen 80;
    server_name example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name example.com;
    
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    
    root /var/www/html;
    index index.html;
    
    location / {
        try_files $uri $uri/ =404;
    }
}`
    }
  ];
  
  res.json(templates);
});

/**
 * @route   GET /api/nginx/status
 * @desc    获取Nginx状态
 * @access  私有
 */
router.get('/status', async (req, res) => {
  try {
    // 检查Nginx是否运行
    const { stdout, stderr } = await execPromise('systemctl is-active nginx');
    const isRunning = stdout.trim() === 'active';
    
    // 获取Nginx版本
    let version = '';
    try {
      const versionResult = await execPromise('nginx -v 2>&1');
      const versionMatch = versionResult.stdout.match(/nginx version: nginx\/(\d+\.\d+\.\d+)/);
      version = versionMatch ? versionMatch[1] : '未知';
    } catch (error) {
      version = '未知';
    }
    
    res.json({
      isRunning,
      version
    });
  } catch (error) {
    res.json({
      isRunning: false,
      version: '未知',
      error: error.message
    });
  }
});

/**
 * @route   POST /api/nginx/action
 * @desc    执行Nginx操作（启动/停止/重启/重载）
 * @access  私有 (仅管理员)
 */
router.post('/action', verifyAdmin, async (req, res) => {
  try {
    const { action } = req.body;
    
    if (!action) {
      return res.status(400).json({ error: '未指定操作类型' });
    }
    
    // 验证操作类型
    if (!['start', 'stop', 'restart', 'reload'].includes(action)) {
      return res.status(400).json({ error: '无效的操作类型' });
    }
    
    // 执行操作
    if (action === 'reload') {
      await execPromise('nginx -s reload');
    } else {
      await execPromise(`systemctl ${action} nginx`);
    }
    
    res.json({
      message: `Nginx ${
        action === 'start' ? '已启动' : 
        action === 'stop' ? '已停止' : 
        action === 'restart' ? '已重启' : 
        '配置已重载'
      }`
    });
  } catch (error) {
    res.status(500).json({ error: `操作失败: ${error.message}` });
  }
});

module.exports = router; 